package com.gitee.linmt.service.impl;

import com.gitee.linmt.entity.SysUser;
import com.gitee.linmt.entity.SysUserRole;
import com.gitee.linmt.exception.ServiceException;
import com.gitee.linmt.repository.SysRoleRepository;
import com.gitee.linmt.repository.SysUserRepository;
import com.gitee.linmt.repository.SysUserRoleRepository;
import com.gitee.linmt.service.SysUserService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户 Service 实现类.
 *
 * @author <a href="mailto:lin-mt@outlook.com">lin-mt</a>
 */
@Service
public class SysUserServiceImpl implements SysUserService {
    
    private final SysUserRepository userRepository;
    
    private final SysUserRoleRepository userRoleRepository;
    
    private final SysRoleRepository roleRepository;
    
    private final PasswordEncoder passwordEncoder;
    
    public SysUserServiceImpl(SysUserRepository userRepository, SysUserRoleRepository userRoleRepository,
            SysRoleRepository roleRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.userRoleRepository = userRoleRepository;
        this.roleRepository = roleRepository;
        this.passwordEncoder = passwordEncoder;
    }
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userRepository.getByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        List<SysUserRole> sysUserRoles = userRoleRepository.findByUserId(user.getId());
        if (!CollectionUtils.isEmpty(sysUserRoles)) {
            Set<Long> roleIds = sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());
            user.setAuthorities(roleRepository.findAllById(roleIds));
        }
        return user;
    }
    
    @Override
    public SysUser save(SysUser sysUser) {
        if (userRepository.getByUsername(sysUser.getUsername()) != null) {
            throw new ServiceException("S0001", sysUser.getUsername());
        }
        sysUser.setSecretCode(passwordEncoder.encode(sysUser.getSecretCode()));
        return userRepository.saveAndFlush(sysUser);
    }
    
    @Override
    public boolean delete(Long deleteId) {
        userRepository.deleteById(deleteId);
        return true;
    }
    
    @Override
    public SysUser update(SysUser user) {
        SysUser exist = userRepository.getByUsername(user.getUsername());
        if (exist != null && !exist.getId().equals(user.getId())) {
            throw new ServiceException("S0001", user.getUsername());
        }
        return userRepository.saveAndFlush(user);
    }
}
